package io.gitee.hefren.hhregistry.controller;

import static com.google.common.base.Preconditions.*;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import io.gitee.hefren.hhregistry.beans.HhregsitrySnapshot;
import io.gitee.hefren.hhregistry.beans.InstanceMeta;
import io.gitee.hefren.hhregistry.cluster.Cluster;
import io.gitee.hefren.hhregistry.cluster.Server;
import io.gitee.hefren.hhregistry.service.RegisterService;
import io.gitee.hefren.hhregistry.service.impl.HhRegisterService;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * @Date 2024/5/13
 * @Author lifei
 */
@RestController
@RequestMapping(value = "/hhregistryController")
public class HhregistryController {

    private static final Logger log = LoggerFactory.getLogger(HhregistryController.class);

    @Resource
    private RegisterService registerService;

    @Resource
    private Cluster cluster;

    private void checkLeader() {
        checkState(Objects.nonNull(cluster.self()) && cluster.self().getLeader(), "only leader can write");
    }

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public InstanceMeta register(@RequestParam("server") String server, @RequestBody InstanceMeta instanceMeta) {
        log.debug("====> register server: {}, instance: {}", server, instanceMeta);
        checkLeader();
        return registerService.register(server, instanceMeta);
    }

    @RequestMapping(value = "/unregister", method = RequestMethod.POST)
    public InstanceMeta unregister(@RequestParam("server") String server, @RequestBody InstanceMeta instanceMeta) {
        log.debug("====> unregister server: {}, instance: {}", server, instanceMeta);
        checkLeader();
        return registerService.unregister(server, instanceMeta);
    }

    @RequestMapping(value = "/findAllInstances", method = RequestMethod.GET)
    public List<InstanceMeta> findAllInstances(@RequestParam("server") String server) {
        log.debug("====> findAllInstances server: {}", server);
        return registerService.findAllInstances(server);
    }

    /**
     * 刷新 servers 和instanceMeta 的时间戳
     * @param servers
     * @param instanceMeta
     * @return
     */
    @RequestMapping(value = "/renews", method = RequestMethod.POST)
    public Long renews(@RequestParam("servers") String servers, @RequestBody InstanceMeta instanceMeta) {
        checkLeader();
        List<String> serverList = Lists.newArrayList(Splitter.on(",").omitEmptyStrings().trimResults()
                .split(Optional.ofNullable(servers).orElse("")));
        log.debug("===> renew servers: {}", serverList);
        return registerService.renew(instanceMeta, serverList.toArray(new String[0]));
    }

    /**
     * 获取server 的版本
     * @param server
     * @return
     */
    @RequestMapping(value = "/version", method = RequestMethod.GET)
    public Long version(@RequestParam("server") String server) {
        log.debug("====> version server: {}", server);
        return registerService.version(server);
    }

    /**
     * 获取多个server的版本
     * @param servers
     * @return
     */
    @RequestMapping(value = "/versions", method = RequestMethod.GET)
    public Map<String, Long> versions(@RequestParam("servers") String servers) {
        List<String> serverList = Lists.newArrayList(Splitter.on(",").omitEmptyStrings().trimResults()
                .split(Optional.ofNullable(servers).orElse("")));
        log.debug("====> version servers: {}", serverList);
        return registerService.versions(serverList.toArray(new String[0]));
    }

    @RequestMapping(value = "/info", method = RequestMethod.GET)
    public Server info() {
        log.debug("==> info: {}", cluster.self());
        return cluster.self();
    }

    @RequestMapping(value = "/leader", method = RequestMethod.GET)
    public Server leader() {
        log.debug("==> leader: {}", cluster.leader());
        return cluster.leader();
    }

    @RequestMapping(value = "/cluster", method = RequestMethod.GET)
    public List<Server> cluster() {
        log.debug("===> cluster: {}", cluster.getServerList());
        return cluster.getServerList();
    }

    @RequestMapping(value = "/sf", method = RequestMethod.GET)
    public Server sf() {
        cluster.self().setLeader(true);
        log.debug("==> sf: {}", cluster.self());
        return cluster.self();
    }

    @RequestMapping(value = "/snapshot", method = RequestMethod.GET)
    public HhregsitrySnapshot snapshot() {
        return HhRegisterService.createSnapshot();
    }


}
